package serveur;

/**
 * Class UserServerDelegate
 * 
 * Cette classe permet d'échanger des messages avec le client
 * Les messages échangés sont des objets qui dérive de la classe Message.java 
 * 
 */
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;

import serveur.MainServer.CanalAnnonceurHandler;

import common.SendFile;
import common.base64encoder;

import message.Message;
import message.MessageChooseFolder;
import message.MessageCloseService;
import message.MessageCloseUser;
import message.MessageCreateFolder;
import message.MessageDeleteFolder;
import message.MessageGetFile;
import message.MessageGetFileFullInFolder;
import message.MessageGetFileInFolder;
import message.MessageOpenService;
import message.MessagePutFile;
import message.ReceiveMessage;
import message.SendMessage;

public class UserServerDelegate implements Runnable {

	private Socket mSocket;

	private ObjectInputStream mOis;
	private ObjectOutputStream mOus;
	//Utilisation de ReceiveMessage
	private ReceiveMessage mReceiveMessage;
	//Utilisation de SendMessage
	private SendMessage mSendMessage;
	private Logger logger = Logger.getLogger(MainServer.class.getName());
	//private static final Logger logger = Logger.getLogger(MainServer.class.getName());
	private ExecutorService mPool;
	private CanalAnnonceurHandler mCanalAnnouceurHandler;
	private MainServer mServer;
	private AnnonceurServerDelegate mAnnonceurServerDelegate;
	/**
	 * Constructeur
	 * @param pSock
	 * @param pI
	 * @param mCanalAnnonceur 
	 */
	public UserServerDelegate(Socket pSock, int pI, MainServer server, ExecutorService pool) {
		this.mSocket = pSock;
		this.mPool = pool;
		this.mServer = server;
		
		try {
			this.mOis = new ObjectInputStream(mSocket.getInputStream());
			this.mOus = new ObjectOutputStream(mSocket.getOutputStream());
			
			logger.log(Level.INFO,"Contructeur UserServerDelegate");
		} catch (IOException ex) {
			logger.log(Level.SEVERE,"Unexpected error",ex);
		}
	}

	public void run() {
		String reponse = "TPFTP\n";
		Message reception;
		int messageID = 0;
		Boolean fini = false;
		Boolean authOK = false;	// en prevision pour enregistrer l'etat de l'authentification de l'utilisateur
		
		try {
			while (!fini) {
				// TODO arreter la boucle infinie :)
				
				logger.log(Level.INFO,"Run UserServerDelegate");
				// recuperation de la requete client
				reception = (Message) mOis.readObject();
				messageID = reception.getMessageId();
				
				// tri du message en fonction de son ID
				switch (messageID) {
				// MessageOpenService
				case Message.OpenServiceId:
					MessageOpenService messageOpenService = (MessageOpenService) reception;
					int port = 0;
					// authentification
					if ( messageOpenService.execute() == true )
					{
					//reponse ="Passage dans le case MessageOpenService";
					// Steph : Creation du canal flux de données. A voir quand on le créé.
						mCanalAnnouceurHandler = mServer.new CanalAnnonceurHandler(mPool);
						mCanalAnnouceurHandler.start();
					// Steph : Recuperation du AnnonceurServerDelegate pour pouvoir y avoir accés pour envoyer les données.
						
					}
					mOus.writeObject(reception);
					mOus.flush();
					if ( messageOpenService.execute() == true )
					{
						mOus.writeInt(mCanalAnnouceurHandler.getLocalPort());
					}
					break;
					
				// MessageCloseService
				case Message.CloseServiceId:
					MessageCloseService messageCloseService = (MessageCloseService) reception;
					messageCloseService.execute();
					//reponse ="Passage dans le case MessageCloseService";
					mOus.writeObject(reception);
					fini = true;
					break;
					
					// MessageCloseUser
				case Message.CloseUserId:
					MessageCloseUser MessageCloseUser = (MessageCloseUser) reception;
					MessageCloseUser.execute();
					mOus.writeObject(reception);
					//reponse ="Passage dans le case MessageCloseUser";
					break;
					
				// MessageChooseFolder - CD
				case Message.ChooseFolderId:
					MessageChooseFolder messageChooseFolder = (MessageChooseFolder) reception;
					messageChooseFolder.execute();
					mOus.writeObject(messageChooseFolder);
					break;
					
				// MessageCreateFolder - MKDIR
				case Message.CreateFolderId:
					MessageCreateFolder messageCreateFolder = (MessageCreateFolder) reception;
					messageCreateFolder.execute();
					mOus.writeObject(messageCreateFolder);
					break;
					
				// MessageDeleteFolder
				case Message.DeleteFolderId:
					MessageDeleteFolder messageDeleteFolder = (MessageDeleteFolder) reception;
					messageDeleteFolder.execute();
					mOus.writeObject(messageDeleteFolder);
					break;
					
				// MessageGetFile
				case Message.GetFileId:
					MessageGetFile messageGetFile = (MessageGetFile) reception;
					mAnnonceurServerDelegate = mCanalAnnouceurHandler.getAnnonceurServerDelegate();
					messageGetFile.setM_AnnonceurServerDelegate(mAnnonceurServerDelegate);
					messageGetFile.setmControlSocket(mSocket);
					messageGetFile.execute();
					//mOus.writeUTF("Passage dans le case MessageGetFile");
					break;
					
				// MessageGetFileFullInFolder
				case Message.GetFileFullInFolderId:
					MessageGetFileFullInFolder messageGetFileFullInFolder = (MessageGetFileFullInFolder) reception;
					messageGetFileFullInFolder.execute();
					break;
					
				// MessageGetFileInFolder - LS
				case Message.GetFileInFolderId:
					MessageGetFileInFolder messageGetFileInFolder = (MessageGetFileInFolder) reception;
					messageGetFileInFolder.execute();
					mOus.writeObject(messageGetFileInFolder);
					break;
					
				// MessagePutFile
				case Message.PutFileId:
					MessagePutFile messagePutFile = (MessagePutFile) reception;
					mAnnonceurServerDelegate = mCanalAnnouceurHandler.getAnnonceurServerDelegate();
					messagePutFile.setM_AnnonceurServerDelegate(mAnnonceurServerDelegate);
					messagePutFile.setmControlSocket(mSocket);
					messagePutFile.execute();
					break;

				default:
					break;
				}
				// reponse suite à la bonne reception du message
				//mOus.writeUTF(reponse);
				
				mOus.flush();
			}
		
			// Fermeture des sockets
			mOis.close();
			mOus.close();
			
		} catch (IOException ex) {
			logger.log(Level.SEVERE,"Unexpected error",ex);
		} catch (ClassNotFoundException ex) {
			logger.log(Level.SEVERE,"Unexpected error",ex);
		}
	}
}
